package com.edu.whty.common.tools;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.edu.whty.common.constants.Constant;
import com.edu.whty.common.tools.redis.RedisUtil;
import com.edu.whty.domain.SubjectDto;
import com.edu.whty.domain.UserClassSubjectDto;
import com.edu.whty.domain.UserInfoDto;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class OpenUtil {

    private static Logger logger = LoggerFactory.getLogger(OpenUtil.class);

    private static String openGateDomain;


    @Value("${rrtbk.opengateDomain}")
    public void setOpengateDomain(String opengateDomain) {
        openGateDomain = opengateDomain;
    }

    private static String appId;

    private static String appKey;

    private static String schoolId;


    @Value("${rrtbk.openAppId}")
    public void setOpenAppId(String openAppId) {
        appId = openAppId;
    }


    @Value("${rrtbk.openAppKey}")
    public void setOpenAppKey(String openAppKey) {
        appKey = openAppKey;
    }

    @Value("${rrtbk.orgId}")
    public void setOrgId(String orgId) {
        schoolId = orgId;
    }

    private static RedisUtil redisUtil;

    @Autowired
    private void setRedisUtil(RedisUtil redisUtil) {
        OpenUtil.redisUtil = redisUtil;
    }

    /**
     * 生成token参数
     */
    public static String createToken() throws Exception {

        String openAccessToken = (String) redisUtil.get("open_access_token");
        if (StringUtils.isNotEmpty(openAccessToken) && checkTokenValid(openAccessToken)) {
            return openAccessToken;
        }
        //生成token服务地址
        String openGetAccessTokenUrl = openGateDomain + "/apigateway/getAccessToken";
        String time = String.valueOf(System.currentTimeMillis());
        String paramValues = appId + appKey + time;
        byte[] hmacSHA = ShaEncyrpUtils.getHmacSHA1(paramValues, appKey);
        String keyInfo = ShaEncyrpUtils.bytesToHexString(hmacSHA);
        JSONObject tokenParam = new JSONObject();
        tokenParam.put("appId", appId);
        tokenParam.put("timeStamp", time);
        tokenParam.put("keyInfo", keyInfo);
//        tokenParam.put("platformCode", platformCode);

        String tokenStr = HttpClient.doJSONPostMethod(openGetAccessTokenUrl, tokenParam.toJSONString());
        JSONObject jsb = JSONObject.parseObject(tokenStr);
        if (jsb.getString("retCode").equals("000000")) {
            JSONObject tokenJsb = JSONObject.parseObject(jsb.getString("tokenInfo"));
//            redisUtil.set("open_access_token", tokenJsb.getString("accessToken"), 30 * 60);
            return tokenJsb.getString("accessToken");
        } else {
            return "";
        }
    }

    /**
     * 生成token参数
     */
    public static String createTokenByUrl(String url) throws Exception {

        String openAccessToken = (String) redisUtil.get("open_access_token_999999");
        if (StringUtils.isNotEmpty(openAccessToken) && checkTokenValidByUrl(openAccessToken, url)) {
            return openAccessToken;
        }
        //生成token服务地址
        String openGetAccessTokenUrl = url + "/apigateway/getAccessToken";
        String time = String.valueOf(System.currentTimeMillis());
        String paramValues = appId + appKey + time;
        byte[] hmacSHA = ShaEncyrpUtils.getHmacSHA1(paramValues, appKey);
        String keyInfo = ShaEncyrpUtils.bytesToHexString(hmacSHA);
        JSONObject tokenParam = new JSONObject();
        tokenParam.put("appId", appId);
        tokenParam.put("timeStamp", time);
        tokenParam.put("keyInfo", keyInfo);
//        tokenParam.put("platformCode", platformCode);

        logger.info("生成token:" + openGetAccessTokenUrl + ";请求参数:" + tokenParam.toJSONString());
        String tokenStr = HttpClient.doJSONPostMethod(openGetAccessTokenUrl, tokenParam.toJSONString());
        JSONObject jsb = JSONObject.parseObject(tokenStr);
        if (jsb.getString("retCode").equals("000000")) {
            JSONObject tokenJsb = JSONObject.parseObject(jsb.getString("tokenInfo"));
            redisUtil.set("open_access_token_999999", tokenJsb.getString("accessToken"), 30 * 60);
            return tokenJsb.getString("accessToken");
        } else {
            return "";
        }
    }


    /**
     * @Author Arthurrr 2019年7月30日
     * @Des: token有两个小时有效期，这里需要验证token是否有效
     */
    private static boolean checkTokenValidByUrl(String openAccessToken, String OpenUrl) {
        try {
            String url = OpenUrl + "/apigateway/validateAccessToken";
            JSONObject param = new JSONObject();
            param.put("accessToken", openAccessToken);
            String aamResponse = HttpClient.doJSONPostMethod(url, param.toJSONString());
            logger.info("调用开放平台接口url及参数 ==> " + url + ",param:" + param.toString());
            logger.info("开放平台返回接口数据 ==> " + aamResponse);
            net.sf.json.JSONObject jsonObj = net.sf.json.JSONObject.fromObject(aamResponse);
            String resultCode = jsonObj.optString("retCode");
            if (Constant.SUCCESS_CODE.equals(resultCode)) {
                return true;
            }
        } catch (Exception e) {
            logger.error("", e);
        }
        return false;
    }

    /**
     * @Author Arthurrr 2019年7月30日
     * @Des: token有两个小时有效期，这里需要验证token是否有效
     */
    private static boolean checkTokenValid(String openAccessToken) {
        try {
            String url = openGateDomain + "/apigateway/validateAccessToken";
            JSONObject param = new JSONObject();
            param.put("accessToken", openAccessToken);
            String aamResponse = HttpClient.doJSONPostMethod(url, param.toJSONString());
            logger.info("调用开放平台接口url及参数 ==> " + url + ",param:" + param.toString());
            logger.info("开放平台返回接口数据 ==> " + aamResponse);
            net.sf.json.JSONObject jsonObj = net.sf.json.JSONObject.fromObject(aamResponse);
            String resultCode = jsonObj.optString("retCode");
            if (Constant.SUCCESS_CODE.equals(resultCode)) {
                return true;
            }
        } catch (Exception e) {
            logger.error("", e);
        }
        return false;
    }


    /**
     * 查询学校所有老师
     *
     * @author luyao
     * @date 2021/5/18
     */
    public static List<String> getSchoolUserIds() throws Exception {
        List<String> userArr = new ArrayList<>();
        if (redisUtil.hasKey(schoolId + "_userIds")) {
            userArr = (List<String>) redisUtil.get(schoolId + "_userIds");
        }
        if (userArr.size() == 0) {
            List<String> userArr0 = new ArrayList<>();
            userArr = querySchoolIds(1, userArr0);
            if (userArr.size() != 0 || userArr != null) {
                redisUtil.set(schoolId + "_userIds", userArr, 60 * 60);
            }
            return userArr;
        } else {
            return userArr;
        }
    }

    static List<String> querySchoolIds(Integer curPage, List<String> userArr) throws Exception {
        logger.info("通讯录7.0的业务逻辑，查询学校教师学科信息");
        String url = openGateDomain + "/user/api/org/get-school-teacher-list?accessToken=" + createToken();
        JSONObject param = new JSONObject();
        String[] strArr = {schoolId};
        param.put("top_org_id", strArr);
        param.put("page", curPage);
        param.put("has_class", 0);
        param.put("page_size", 100);
        String aamResponse = HttpClient.doJSONPostMethod(url, param.toJSONString());
        logger.info("调用开放平台接口url及参数 ==> " + url + ",param:" + param.toString());
        logger.info("开放平台返回接口数据 ==> " + aamResponse);
        net.sf.json.JSONObject jsonObj = net.sf.json.JSONObject.fromObject(aamResponse);
        String resultCode = jsonObj.optString("code");
        if (Constant.SUCCESS_CODE.equals(resultCode)) {
            net.sf.json.JSONObject resultObj = jsonObj.optJSONObject("result");
            net.sf.json.JSONArray list = resultObj.optJSONArray("member_list");
            int count = resultObj.optInt("count");
            if (list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    net.sf.json.JSONObject json = list.getJSONObject(i);
                    userArr.add(json.optString("user_id"));
                }
                if (curPage * 100 < count) {
                    userArr = querySchoolIds(curPage + 1, userArr);
                }
                return userArr;
            } else {
                return null;
            }

        } else {
            return null;
        }
    }

    /**
     * 查询学校所有老师
     *
     * @param curPage
     * @param orgId
     * @return
     * @throws Exception
     */
    public static List<UserInfoDto> querySchoolTeachers(Integer curPage, String orgId) throws Exception {
        logger.info("通讯录7.0的业务逻辑，获取组织成员详细列表");

        List<UserInfoDto> userList = new ArrayList<>();
        String url = openGateDomain + "/user/api/user/get-org-member-list?top_org_id=" + orgId + "&page=" + curPage + "&page_size=100" + "&accessToken=" + createToken();
        String aamResponse = HttpClient.doGetMethod(url);

        logger.info("调用开放平台接口url及参数 ==> " + url);
        logger.info("开放平台返回接口数据 ==> " + aamResponse);
        JSONObject jsonObj = JSONObject.parseObject(aamResponse);
        String resultCode = jsonObj.getString("code");
        if (Constant.SUCCESS_CODE.equals(resultCode)) {
            JSONObject resultObj = jsonObj.getJSONObject("result");
            JSONArray list = resultObj.getJSONArray("member_list");

            userList.addAll(list.toJavaList(UserInfoDto.class));
            int count = resultObj.getInteger("count");
            if (list.size() > 0) {
                if (curPage * 100 < count) {
                    userList.addAll(querySchoolTeachers(curPage + 1, orgId));
                }
            }
        }
        return userList;
    }

//    @Cacheable(value = "cache2", unless = "#result == null")
    public List<UserClassSubjectDto> querySchoolTeacherSubject(Integer curPage, String orgId) throws Exception {
        logger.info("通讯录7.0的业务逻辑，查询学校教师学科信息");
        List<UserClassSubjectDto> subjectList = new ArrayList<>();
        String url = openGateDomain + "/user/api/org/get-school-teacher-list?accessToken=" + createToken();
        JSONObject param = new JSONObject();
        String[] strArr = {orgId};
        param.put("top_org_id", strArr);
        param.put("page", curPage);
        param.put("has_class", 0);
        param.put("page_size", 100);
        String aamResponse = HttpClient.doJSONPostMethod(url, param.toJSONString());
        logger.info("调用开放平台接口url及参数 ==> " + url + ",param:" + param.toString());
        logger.info("开放平台返回接口数据 ==> " + aamResponse);
        JSONObject jsonObj = JSONObject.parseObject(aamResponse);
        String resultCode = jsonObj.getString("code");

        if (Constant.SUCCESS_CODE.equals(resultCode)) {
            JSONObject resultObj = jsonObj.getJSONObject("result");
            JSONArray list = resultObj.getJSONArray("member_list");
            subjectList.addAll(list.toJavaList(UserClassSubjectDto.class));
            int count = resultObj.getInteger("count");
            if (list.size() > 0) {
                if (curPage * 100 < count) {
                    subjectList.addAll(querySchoolTeacherSubject(curPage + 1, orgId));
                }
            }
        }
        return subjectList;
    }
}
